//-----------------------------------------------------------------------------
// File: LineSegmentShape.cs
//
// Copyright (c) Dmitry Shuklin. All rights reserved.
//-----------------------------------------------------------------------------
using System;
using System.Drawing;
using System.Windows.Forms;
using Microsoft.DirectX;
using Microsoft.DirectX.Direct3D;
using Direct3D = Microsoft.DirectX.Direct3D;

namespace ObjectiveDraw.Platform
{
	/// <summary>
	/// Summary description for LineSegmentShape.
	/// </summary>
	public class LineSegmentShape : DualPointShapeBase
	{
		public const string SystemComponentId = "ObjectiveDraw.LineSegmentShape";
		public LineSegmentShape()
		{
			//
			// TODO: Add constructor logic here
			//
		}


		#region IDrawerShape Members

		public override float DistanceFrom(ObjectiveDraw.Platform.DrawerChartBase control, PointF point)
		{
			DrawerChartContext context = control.Context;

			float xo1 = OffsetFromAbscissa(control, this.AbscissaBegin);
			float yo1 = OffsetFromOrdinate(control, this.OrdinateBegin);

			float xo2 = OffsetFromAbscissa(control, this.AbscissaEnd);
			float yo2 = OffsetFromOrdinate(control, this.OrdinateEnd);

			double SinL;
			double CosL;
			double span = this.AbscissaEnd - this.AbscissaBegin;
			float height = this.OrdinateEnd - this.OrdinateBegin;
			
			double l = Math.Sqrt(span * span + height * height);
			
			if(l > 0)
			{
				SinL = height / l;
				CosL = span / l;
			}
			else
			{
				SinL = 0;
				CosL = 1;
			}

			double a1 = CosL * context.AbscissaPosition.Scale;
			double b1 = - SinL * context.OrdinatePosition.Scale;
			double l1 = Math.Sqrt(a1*a1 + b1*b1);

			double SinL1 = b1 / l1;
			double CosL1 = a1 / l1;

			double dx1 = point.X - xo1;
			double dy1 = point.Y - yo1;

			double dx2 = xo2 - point.X;
			double dy2 = yo2 - point.Y;

			double da = Math.Abs(dx1 * SinL1 - dy1 * CosL1);

			int ss = Math.Sign(CosL1 * SinL1);
			if( ((Math.Sign(dx1 * SinL1 + da) != ss && ss!=0) || Math.Sign(dx1 * CosL1) < 0) || ((Math.Sign( dy1 * CosL1 - da) != ss && ss!=0) || Math.Sign(dy1 * SinL1) < 0)  ) 
			{
				return (float)Math.Sqrt(dx1*dx1 + dy1*dy1);
			}
			if( ((Math.Sign(dx2 * SinL1 + da) != ss && ss!=0) || Math.Sign(dx2 * CosL1) < 0) || ((Math.Sign( dy2 * CosL1 - da) != ss && ss!=0) || Math.Sign(dy2 * SinL1) < 0)  ) 
			{
				return (float)Math.Sqrt(dx2*dx2 + dy2*dy2);
			}

			return (float)da;
		}

		public override void RenderShape(DrawerChartBase control, ChartInfoArgs cinfo, Cerebrum.Direct3D.Forms.RenderEventArgs re, float z)
		{
			base.RenderShape (control, cinfo, re, z);

			Microsoft.DirectX.Direct3D.Device device = re.Device;
			
			float x1 = OffsetFromAbscissa(control, this.AbscissaBegin);
			float x2 = OffsetFromAbscissa(control, this.AbscissaEnd);

			float y1 = OffsetFromOrdinate(control, this.OrdinateBegin);
			float y2 = OffsetFromOrdinate(control, this.OrdinateEnd);

			int clr = this.m_ForeColor.ToArgb();

			VertexBuffer VertexBuffer = new VertexBuffer(typeof(CustomVertex.TransformedColored), 2, device, Usage.WriteOnly, CustomVertex.TransformedColored.Format, Pool.SystemMemory);

			device.VertexFormat = CustomVertex.TransformedColored.Format;

			// set the vertexbuffer stream source
			device.SetStreamSource(0, VertexBuffer, 0, VertexInformation.GetFormatSize(CustomVertex.TransformedColored.Format));
			// set fill mode
			device.RenderState.FillMode = FillMode.Solid;


			CustomVertex.TransformedColored[] verts = (CustomVertex.TransformedColored[])VertexBuffer.Lock(0,0); // Lock the buffer (which will return our structs)

			verts[0].Position = new Vector4(x1, y1, z, 1.0f);
			verts[0].Color = clr;

			verts[1].Position = new Vector4(x2, y2, z, 1.0f);
			verts[1].Color = clr;

			VertexBuffer.Unlock();


			//use the indices buffer
			device.DrawPrimitives(PrimitiveType.LineList, 0, 1);

			VertexBuffer.Dispose();		
		}

		#endregion

	}
}
